#ifdef DEBUG
   #include "zhi.h"
   //在fnDebug中绑定函数名
   void bindDebugFnName(虚拟机* 虚拟机S, 函数调试S* fnDebug,
	 const char* name, uint32_t 长度) {
      ASSERT(fnDebug->fnName == NULL, "debug.name has bound!");
      fnDebug->fnName = 分配数组内存M(虚拟机S, char, 长度 + 1);
      memcpy(fnDebug->fnName, name, 长度); 
      fnDebug->fnName[长度] = '\0';
   }

   void bindDebugFnName2(虚拟机* 虚拟机S, 函数对象S* fn,
	   const char* name, uint32_t 长度) {
	   ASSERT(fn->debug->fnName == NULL, "debug.name has bound!");
	   fn->debug->fnName = 分配数组内存M(虚拟机S, char, 长度 + 1);
	   memcpy(fn->debug->fnName, name, 长度);
	   fn->debug->fnName[长度] = '\0';
   }

   //打印栈
   void dumpStack(线程对象S* thread) {
      printf("(thread %p) stack:%p, esp:%p, slots:%ld ",
	    thread, thread->stack, thread->esp, thread->esp - thread->stack);
      Value* slot = thread->stack;
      while (slot < thread->esp) {
	 dumpValue(*slot);
	 printf(" | ");
	 slot++;
      }
      printf("\n");
   }
   
   //打印对象
   static void dumpObject(对象头S* obj) {
      switch (obj->type) {
	 case 对象类型_类:
	    printf("[class %s %p]", ((Class*)obj)->name->value.start, obj); 
	    break;
	 case 对象类型_闭包:
	    printf("[closure %p]", obj);
	    break;
	 case 对象类型_线程:
	    printf("[thread %p]", obj);
	    break;
	 case 对象类型_函数:
	    printf("[fn %p]", obj);
	    break;
	 case 对象类型_对象实例:
	    printf("[instance %p]", obj);
	    break;
	 case 对象类型_列表:
	    printf("[list %p]", obj);
	    break;
	 case 对象类型_散列数组:
	    printf("[map %p]", obj);
	    break;
	 case 对象类型_模块作用域:
	    printf("[module %p]", obj);
	    break;
	 case 对象类型_范围:
	    printf("[range %p]", obj);
	    break;
	 case 对象类型_字符串:
	    printf("[string %s]", ((字符串对象S*)obj)->value.start);
	    break;
	 case 对象类型_自由变量 : 
	    printf("[upvalue %p]", obj); 
	    break;
	 default: 
	    printf("[unknown object %d]", obj->type);
	    break;
      }
   }

   //打印value
   void dumpValue(Value value) {
      switch (value.type) {
	 case 值类型_假:     printf("false"); break;
	 case 值类型_空:      printf("null"); break;
	 case 值类型_数字:       printf("%.14g", VALUE_TO_NUM(value)); break;
	 case 值类型_真:      printf("true"); break;
	 case 值类型_对象:       dumpObject(VALUE_TO_OBJ(value)); break;
	 case 值类型_未定义: 没有达到M();
      }
   }

   //打印一条指令
   static int dumpOneInstruction(虚拟机* 虚拟机S, 函数对象S* fn, int i, int* lastLine) {
      int start = i;
      uint8_t* bytecode = fn->instrStream.数据缓冲区;
      操作码S opCode = (操作码S)bytecode[i];

      int 行号 = fn->debug->行号.数据缓冲区[i];

      if (lastLine == NULL || *lastLine != 行号) {
	 printf("%4d:", 行号);    //输出源码行号
	 if (lastLine != NULL) {
	    *lastLine = 行号;
	 }
      } else {
	 //不用输出源码行了,还是输出的lastLine行的指令流,空出行号的位置即可
	 printf("     ");
      }

      printf(" %04d  ", i++);   //输出指令流中的位置

      #define READ_BYTE() (bytecode[i++])
      #define READ_SHORT() (i += 2, (bytecode[i - 2] << 8) | bytecode[i - 1])

      #define BYTE_INSTRUCTION(name) \
	  printf("%-16s %5d\n", name, READ_BYTE()); \
	  break; \

      switch (opCode) {
	 case OPCODE_LOAD_CONSTANT: {
	    int constant = READ_SHORT();
	    printf("%-16s %5d '", "LOAD_CONSTANT", constant);
	    dumpValue(fn->constants.数据缓冲区[constant]);
	    printf("'\n");
	    break;
	 }

	 case OPCODE_PUSH_NULL:  printf("PUSH_NULL\n"); break;
	 case OPCODE_PUSH_FALSE: printf("PUSH_FALSE\n"); break;
	 case OPCODE_PUSH_TRUE:  printf("PUSH_TRUE\n"); break;

	 case OPCODE_LOAD_LOCAL_VAR: BYTE_INSTRUCTION("LOAD_LOCAL_VAR");
	 case OPCODE_STORE_LOCAL_VAR: BYTE_INSTRUCTION("STORE_LOCAL_VAR");
	 case OPCODE_LOAD_UPVALUE: BYTE_INSTRUCTION("LOAD_UPVALUE");
	 case OPCODE_STORE_UPVALUE: BYTE_INSTRUCTION("STORE_UPVALUE");

	 case OPCODE_LOAD_MODULE_VAR: {
	    int slot = READ_SHORT();
	    printf("%-16s %5d '%s'\n", "LOAD_MODULE_VAR", slot,
		 fn->module->moduleVarName.数据缓冲区[slot].str);
	    break;
	 }

	 case OPCODE_STORE_MODULE_VAR: {
	    int slot = READ_SHORT();
	    printf("%-16s %5d '%s'\n", "STORE_MODULE_VAR", slot,
		 fn->module->moduleVarName.数据缓冲区[slot].str);
	    break;
	 }

	 case OPCODE_LOAD_THIS_FIELD: BYTE_INSTRUCTION("LOAD_THIS_FIELD");
	 case OPCODE_STORE_THIS_FIELD: BYTE_INSTRUCTION("STORE_THIS_FIELD");
	 case OPCODE_LOAD_FIELD: BYTE_INSTRUCTION("LOAD_FIELD");
	 case OPCODE_STORE_FIELD: BYTE_INSTRUCTION("STORE_FIELD");

	 case OPCODE_POP: printf("POP\n"); break;

	 case OPCODE_CALL0:
	 case OPCODE_CALL1:
	 case OPCODE_CALL2:
	 case OPCODE_CALL3:
	 case OPCODE_CALL4:
	 case OPCODE_CALL5:
	 case OPCODE_CALL6:
	 case OPCODE_CALL7:
	 case OPCODE_CALL8:
	 case OPCODE_CALL9:
	 case OPCODE_CALL10:
	 case OPCODE_CALL11:
	 case OPCODE_CALL12:
	 case OPCODE_CALL13:
	 case OPCODE_CALL14:
	 case OPCODE_CALL15:
	 case OPCODE_CALL16: {
	    int numArgs = bytecode[i - 1] - OPCODE_CALL0;
	    int symbol = READ_SHORT();
	    printf("CALL%-11d %5d '%s'\n", numArgs, symbol,
		 虚拟机S->所有类的方法名称.数据缓冲区[symbol].str);
	    break;
	 }

	 case OPCODE_SUPER0:
	 case OPCODE_SUPER1:
	 case OPCODE_SUPER2:
	 case OPCODE_SUPER3:
	 case OPCODE_SUPER4:
	 case OPCODE_SUPER5:
	 case OPCODE_SUPER6:
	 case OPCODE_SUPER7:
	 case OPCODE_SUPER8:
	 case OPCODE_SUPER9:
	 case OPCODE_SUPER10:
	 case OPCODE_SUPER11:
	 case OPCODE_SUPER12:
	 case OPCODE_SUPER13:
	 case OPCODE_SUPER14:
	 case OPCODE_SUPER15:
	 case OPCODE_SUPER16: {
	    int numArgs = bytecode[i - 1] - OPCODE_SUPER0;
	    int symbol = READ_SHORT();
	    int superclass = READ_SHORT();
	    printf("SUPER%-10d %5d '%s' %5d\n", numArgs, symbol,
		 虚拟机S->所有类的方法名称.数据缓冲区[symbol].str, superclass);
	    break;
	 }

	 case OPCODE_JUMP: {
	    int offset = READ_SHORT();
	    printf("%-16s offset:%-5d abs:%d\n", "JUMP", offset, i + offset);
	    break;
	 }

	 case OPCODE_LOOP: {
	    int offset = READ_SHORT();
	    printf("%-16s offset:%-5d abs:%d\n", "LOOP", offset, i - offset);
	    break;
	 }

	 case OPCODE_JUMP_IF_FALSE: {
	    int offset = READ_SHORT();
	    printf("%-16s offset:%-5d abs:%d\n", "JUMP_IF_FALSE", offset, i + offset);
	    break;
	 }

	 case OPCODE_AND: {
	    int offset = READ_SHORT();
	    printf("%-16s offset:%-5d abs:%d\n", "AND", offset, i + offset);
	    break;
	 }

	 case OPCODE_OR: {
	    int offset = READ_SHORT();
	    printf("%-16s offset:%-5d abs:%d\n", "OR", offset, i + offset);
	    break;
	 }

	 case OPCODE_CLOSE_UPVALUE: 
	    printf("CLOSE_UPVALUE\n");
	    break;

	 case OPCODE_RETURN:
	    printf("RETURN\n"); 
	    break;

	 case OPCODE_CREATE_CLOSURE: {
	    int constant = READ_SHORT();
	    printf("%-16s %5d ", "CREATE_CLOSURE", constant);
	    dumpValue(fn->constants.数据缓冲区[constant]);
	    printf(" ");
	    函数对象S* loadedFn = VALUE_TO_OBJFN(fn->constants.数据缓冲区[constant]);
	    uint32_t j; 
	    for (j = 0; j < loadedFn->upvalueNum; j++) {
	       int isLocal = READ_BYTE();
	       int index = READ_BYTE();
	       if (j > 0) printf(", ");
	       printf("%s %d", isLocal ? "local" : "upvalue", index);
	    }
	    printf("\n");
	    break;
	 }

	 case OPCODE_CONSTRUCT:
	    printf("CONSTRUCT\n");
	    break;
	  
	 case OPCODE_CREATE_CLASS: {
	    int numFields = READ_BYTE();
	    printf("%-16s %5d fields\n", "CREATE_CLASS", numFields);
	    break;
	 }

	 case OPCODE_INSTANCE_METHOD: {
	    int symbol = READ_SHORT();
	    printf("%-16s %5d '%s'\n", "INSTANCE_METHOD", symbol,
		 虚拟机S->所有类的方法名称.数据缓冲区[symbol].str);
	    break;
	 }

	 case OPCODE_STATIC_METHOD: {
	    int symbol = READ_SHORT();
	    printf("%-16s %5d '%s'\n", "STATIC_METHOD", symbol,
		 虚拟机S->所有类的方法名称.数据缓冲区[symbol].str);
	    break;
	 }

	 case OPCODE_END:
	    printf("END\n");
	    break;

	 default:
	    printf("UKNOWN! [%d]\n", bytecode[i - 1]);
	    break;
      }

      //返回指令占用的字节数
      if (opCode == OPCODE_END) {
	 return -1;
      }
      return i - start;

      #undef READ_BYTE
      #undef READ_SHORT
      #undef BYTE_INSTRUCTION
   }

   //打印指令
   void dumpInstructions(虚拟机* 虚拟机S, 函数对象S* fn) {
      printf("module:[%s]\tfunction:[%s]\n",
	    fn->module->name == NULL ? "<core>" : fn->module->name->value.start,
	    fn->debug->fnName);

      int i = 0;
      int lastLine = -1;
      while (true) {
	 int offset = dumpOneInstruction(虚拟机S, fn, i, &lastLine);
	 if (offset == -1) break;
	 i += offset;
      }
      printf("\n");
   }


   //打印栈
   void fdumpStack(线程对象S* thread) {
	   fprintf(gfnFile,"(thread %p) stack:%p, esp:%p, slots:%ld ",
		   thread, thread->stack, thread->esp, thread->esp - thread->stack);
	   Value* slot = thread->stack;
	   while (slot < thread->esp) {
		   fdumpValue(*slot);
		   fprintf(gfnFile, " | ");
		   slot++;
	   }
	   fprintf(gfnFile, "\n");
   }

   //打印对象
   static void fdumpObject(对象头S* obj) {
	   switch (obj->type) {
	   case 对象类型_类:
		   fprintf(gfnFile, "[class %s %p]", ((Class*)obj)->name->value.start, obj);
		   break;
	   case 对象类型_闭包:
		   fprintf(gfnFile, "[closure %p]", obj);
		   break;
	   case 对象类型_线程:
		   fprintf(gfnFile, "[thread %p]", obj);
		   break;
	   case 对象类型_函数:
		   fprintf(gfnFile, "[fn %p]", obj);
		   break;
	   case 对象类型_对象实例:
		   fprintf(gfnFile, "[instance %p]", obj);
		   break;
	   case 对象类型_列表:
		   fprintf(gfnFile, "[list %p]", obj);
		   break;
	   case 对象类型_散列数组:
		   fprintf(gfnFile, "[map %p]", obj);
		   break;
	   case 对象类型_模块作用域:
		   fprintf(gfnFile, "[module %p]", obj);
		   break;
	   case 对象类型_范围:
		   fprintf(gfnFile, "[range %p]", obj);
		   break;
	   case 对象类型_字符串:
		   fprintf(gfnFile, "[string %s]", ((字符串对象S*)obj)->value.start);
		   break;
	   case 对象类型_自由变量:
		   fprintf(gfnFile, "[upvalue %p]", obj);
		   break;
	   default:
		   fprintf(gfnFile, "[unknown object %d]", obj->type);
		   break;
	   }
   }

   //打印value
   void fdumpValue(Value value) {
	   switch (value.type) {
	   case 值类型_假:     fprintf(gfnFile, "false"); break;
	   case 值类型_空:      fprintf(gfnFile, "null"); break;
	   case 值类型_数字:       fprintf(gfnFile, "%.14g", VALUE_TO_NUM(value)); break;
	   case 值类型_真:      fprintf(gfnFile, "true"); break;
	   case 值类型_对象:       fdumpObject(VALUE_TO_OBJ(value)); break;
	   case 值类型_未定义: 没有达到M();
	   }
   }

   //打印一条指令
   static int fdumpOneInstruction(虚拟机* 虚拟机S, 函数对象S* fn, int i, int* lastLine) {
	   int start = i;
	   uint8_t* bytecode = fn->instrStream.数据缓冲区;
	   操作码S opCode = (操作码S)bytecode[i];

	   int 行号 = fn->debug->行号.数据缓冲区[i];

	   if (lastLine == NULL || *lastLine != 行号) {
		   fprintf(gfnFile, "%4d:", 行号);    //输出源码行号
		   if (lastLine != NULL) {
			   *lastLine = 行号;
		   }
	   }
	   else {
		   //不用输出源码行了,还是输出的lastLine行的指令流,空出行号的位置即可
		   fprintf(gfnFile, "     ");
	   }

	   fprintf(gfnFile, " %04d  ", i++);   //输出指令流中的位置

#define READ_BYTE() (bytecode[i++])
#define READ_SHORT() (i += 2, (bytecode[i - 2] << 8) | bytecode[i - 1])

#define BYTE_INSTRUCTION(name) \
	  fprintf(gfnFile,"%-16s %5d\n", name, READ_BYTE()); \
	  break; \

	   switch (opCode) {
	   case OPCODE_LOAD_CONSTANT: {
		   int constant = READ_SHORT();
		   fprintf(gfnFile, "%-16s %5d '", "LOAD_CONSTANT", constant);
		   fdumpValue(fn->constants.数据缓冲区[constant]);
		   fprintf(gfnFile, "'\n");
		   break;
	   }

	   case OPCODE_PUSH_NULL:  fprintf(gfnFile, "PUSH_NULL\n"); break;
	   case OPCODE_PUSH_FALSE: fprintf(gfnFile, "PUSH_FALSE\n"); break;
	   case OPCODE_PUSH_TRUE:  fprintf(gfnFile, "PUSH_TRUE\n"); break;

	   case OPCODE_LOAD_LOCAL_VAR: BYTE_INSTRUCTION("LOAD_LOCAL_VAR");
	   case OPCODE_STORE_LOCAL_VAR: BYTE_INSTRUCTION("STORE_LOCAL_VAR");
	   case OPCODE_LOAD_UPVALUE: BYTE_INSTRUCTION("LOAD_UPVALUE");
	   case OPCODE_STORE_UPVALUE: BYTE_INSTRUCTION("STORE_UPVALUE");

	   case OPCODE_LOAD_MODULE_VAR: {
		   int slot = READ_SHORT();
		   fprintf(gfnFile, "%-16s %5d '%s'\n", "LOAD_MODULE_VAR", slot,
			   fn->module->moduleVarName.数据缓冲区[slot].str);
		   break;
	   }

	   case OPCODE_STORE_MODULE_VAR: {
		   int slot = READ_SHORT();
		   fprintf(gfnFile, "%-16s %5d '%s'\n", "STORE_MODULE_VAR", slot,
			   fn->module->moduleVarName.数据缓冲区[slot].str);
		   break;
	   }

	   case OPCODE_LOAD_THIS_FIELD: BYTE_INSTRUCTION("LOAD_THIS_FIELD");
	   case OPCODE_STORE_THIS_FIELD: BYTE_INSTRUCTION("STORE_THIS_FIELD");
	   case OPCODE_LOAD_FIELD: BYTE_INSTRUCTION("LOAD_FIELD");
	   case OPCODE_STORE_FIELD: BYTE_INSTRUCTION("STORE_FIELD");

	   case OPCODE_POP: fprintf(gfnFile, "POP\n"); break;

	   case OPCODE_CALL0:
	   case OPCODE_CALL1:
	   case OPCODE_CALL2:
	   case OPCODE_CALL3:
	   case OPCODE_CALL4:
	   case OPCODE_CALL5:
	   case OPCODE_CALL6:
	   case OPCODE_CALL7:
	   case OPCODE_CALL8:
	   case OPCODE_CALL9:
	   case OPCODE_CALL10:
	   case OPCODE_CALL11:
	   case OPCODE_CALL12:
	   case OPCODE_CALL13:
	   case OPCODE_CALL14:
	   case OPCODE_CALL15:
	   case OPCODE_CALL16: {
		   int numArgs = bytecode[i - 1] - OPCODE_CALL0;
		   int symbol = READ_SHORT();
		   fprintf(gfnFile, "CALL%-11d %5d '%s'\n", numArgs, symbol,
			   虚拟机S->所有类的方法名称.数据缓冲区[symbol].str);
		   break;
	   }

	   case OPCODE_SUPER0:
	   case OPCODE_SUPER1:
	   case OPCODE_SUPER2:
	   case OPCODE_SUPER3:
	   case OPCODE_SUPER4:
	   case OPCODE_SUPER5:
	   case OPCODE_SUPER6:
	   case OPCODE_SUPER7:
	   case OPCODE_SUPER8:
	   case OPCODE_SUPER9:
	   case OPCODE_SUPER10:
	   case OPCODE_SUPER11:
	   case OPCODE_SUPER12:
	   case OPCODE_SUPER13:
	   case OPCODE_SUPER14:
	   case OPCODE_SUPER15:
	   case OPCODE_SUPER16: {
		   int numArgs = bytecode[i - 1] - OPCODE_SUPER0;
		   int symbol = READ_SHORT();
		   int superclass = READ_SHORT();
		   fprintf(gfnFile, "SUPER%-10d %5d '%s' %5d\n", numArgs, symbol,
			   虚拟机S->所有类的方法名称.数据缓冲区[symbol].str, superclass);
		   break;
	   }

	   case OPCODE_JUMP: {
		   int offset = READ_SHORT();
		   fprintf(gfnFile, "%-16s offset:%-5d abs:%d\n", "JUMP", offset, i + offset);
		   break;
	   }

	   case OPCODE_LOOP: {
		   int offset = READ_SHORT();
		   fprintf(gfnFile, "%-16s offset:%-5d abs:%d\n", "LOOP", offset, i - offset);
		   break;
	   }

	   case OPCODE_JUMP_IF_FALSE: {
		   int offset = READ_SHORT();
		   fprintf(gfnFile, "%-16s offset:%-5d abs:%d\n", "JUMP_IF_FALSE", offset, i + offset);
		   break;
	   }

	   case OPCODE_AND: {
		   int offset = READ_SHORT();
		   fprintf(gfnFile, "%-16s offset:%-5d abs:%d\n", "AND", offset, i + offset);
		   break;
	   }

	   case OPCODE_OR: {
		   int offset = READ_SHORT();
		   fprintf(gfnFile, "%-16s offset:%-5d abs:%d\n", "OR", offset, i + offset);
		   break;
	   }

	   case OPCODE_CLOSE_UPVALUE:
		   fprintf(gfnFile, "CLOSE_UPVALUE\n");
		   break;

	   case OPCODE_RETURN:
		   fprintf(gfnFile, "RETURN\n");
		   break;

	   case OPCODE_CREATE_CLOSURE: {
		   int constant = READ_SHORT();
		   fprintf(gfnFile, "%-16s %5d ", "CREATE_CLOSURE", constant);
		   fdumpValue(fn->constants.数据缓冲区[constant]);
		   fprintf(gfnFile, " ");
		   函数对象S* loadedFn = VALUE_TO_OBJFN(fn->constants.数据缓冲区[constant]);
		   uint32_t j;
		   for (j = 0; j < loadedFn->upvalueNum; j++) {
			   int isLocal = READ_BYTE();
			   int index = READ_BYTE();
			   if (j > 0) fprintf(gfnFile, ", ");
			   fprintf(gfnFile, "%s %d", isLocal ? "local" : "upvalue", index);
		   }
		   fprintf(gfnFile, "\n");
		   break;
	   }

	   case OPCODE_CONSTRUCT:
		   fprintf(gfnFile, "CONSTRUCT\n");
		   break;

	   case OPCODE_CREATE_CLASS: {
		   int numFields = READ_BYTE();
		   fprintf(gfnFile, "%-16s %5d fields\n", "CREATE_CLASS", numFields);
		   break;
	   }

	   case OPCODE_INSTANCE_METHOD: {
		   int symbol = READ_SHORT();
		   fprintf(gfnFile, "%-16s %5d '%s'\n", "INSTANCE_METHOD", symbol,
			   虚拟机S->所有类的方法名称.数据缓冲区[symbol].str);
		   break;
	   }

	   case OPCODE_STATIC_METHOD: {
		   int symbol = READ_SHORT();
		   fprintf(gfnFile, "%-16s %5d '%s'\n", "STATIC_METHOD", symbol,
			   虚拟机S->所有类的方法名称.数据缓冲区[symbol].str);
		   break;
	   }

	   case OPCODE_END:
		   fprintf(gfnFile, "END\n");
		   break;

	   default:
		   fprintf(gfnFile, "UKNOWN! [%d]\n", bytecode[i - 1]);
		   break;
	   }

	   //返回指令占用的字节数
	   if (opCode == OPCODE_END) {
		   return -1;
	   }
	   return i - start;

#undef READ_BYTE
#undef READ_SHORT
#undef BYTE_INSTRUCTION
   }

   //打印指令
   void fdumpInstructions(虚拟机* 虚拟机S, 函数对象S* fn) {
	   fprintf(gfnFile, "module:[%s]\tfunction:[%s]\n",
		   fn->module->name == NULL ? "<core>" : fn->module->name->value.start,
		   fn->debug->fnName);

	   int i = 0;
	   int lastLine = -1;
	   while (true) {
		   int offset = fdumpOneInstruction(虚拟机S, fn, i, &lastLine);
		   if (offset == -1) break;
		   i += offset;
	   }
	   fprintf(gfnFile, "\n");
   }

#endif
